<?php

declare(strict_types=1);

namespace App\Validator;

use App\Constants\Menu\MenuIsBadgeEnum;
use App\Constants\Menu\MenuBelongToEnum;
use App\Constants\Menu\MenuIsFixedTabEnum;
use App\Constants\Menu\MenuIsFullPageEnum;
use App\Constants\Menu\MenuIsHideEnum;
use App\Constants\Menu\MenuIsHideTabEnum;
use App\Constants\Menu\MenuIsIframeEnum;
use App\Constants\Menu\MenuIsKeepAliveEnum;
use App\Constants\Menu\MenuMethodEnum;
use App\Constants\Menu\MenuStatusEnum;
use App\Constants\Menu\MenuTypeEnum;
use Exception;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Stringable\StrCache;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;

/**
 * 菜单-验证器
 */
class MenuValidator
{
        #[Inject]
        protected ValidatorFactoryInterface $validationFactory;

        /**
         * 验证规则-必须
         */
        public const array RULES = [
                'menuIds' => 'present|required|array',
                'menuId' => 'present|required',
                'pid' => 'present|required',
                'name' => 'present|required|string|between:1,50',
                'title' => 'present|required|string|between:1,50',
                'route' => 'present|required|string|between:1,50',
                'path' => 'present|required|string|between:1,50',
                'activePath' => 'present|required|string|between:1,50',
                'link' => 'present|required|string|between:1,250',
                'icon' => 'present|required|string|between:1,50',
                'permissionMark' => 'present|required|string|between:1,50',
                'badgeText' => 'present|required|string|between:1,50',
                'method' => 'present|required|in:' . MenuMethodEnum::DEFINITION_1->value . ',' .
                        MenuMethodEnum::DEFINITION_2->value . ',' .
                        MenuMethodEnum::DEFINITION_3->value . ',' .
                        MenuMethodEnum::DEFINITION_4->value . ',' .
                        MenuMethodEnum::DEFINITION_5->value . ',' .
                        MenuMethodEnum::DEFINITION_6->value . ',' .
                        MenuMethodEnum::DEFINITION_7->value . ',' .
                        MenuMethodEnum::DEFINITION_8->value,
                'belongTo' => 'present|required|in:' . MenuBelongToEnum::DEFINITION_1->value,
                'status' => 'present|required|in:' . MenuStatusEnum::DEFINITION_1->value . ',' . MenuStatusEnum::DEFINITION_2->value,
                'type' => 'present|required|in:' . MenuTypeEnum::DEFINITION_1->value . ',' . MenuTypeEnum::DEFINITION_2->value,
                'isHide' => 'present|required|in:' . MenuIsHideEnum::DEFINITION_1->value . ',' . MenuIsHideEnum::DEFINITION_2->value,
                'isHideTab' => 'present|required|in:' . MenuIsHideTabEnum::DEFINITION_1->value . ',' . MenuIsHideTabEnum::DEFINITION_2->value,
                'isKeepAlive' => 'present|required|in:' . MenuIsKeepAliveEnum::DEFINITION_1->value . ',' . MenuIsKeepAliveEnum::DEFINITION_2->value,
                'isFixedTab' => 'present|required|in:' . MenuIsFixedTabEnum::DEFINITION_1->value . ',' . MenuIsFixedTabEnum::DEFINITION_2->value,
                'isIframe' => 'present|required|in:' . MenuIsIframeEnum::DEFINITION_1->value . ',' . MenuIsIframeEnum::DEFINITION_2->value,
                'isBadge' => 'present|required|in:' . MenuIsBadgeEnum::DEFINITION_1->value . ',' . MenuIsIframeEnum::DEFINITION_2->value,
                'isFullPage' => 'present|required|in:' . MenuIsFullPageEnum::DEFINITION_1->value . ',' . MenuIsFullPageEnum::DEFINITION_2->value,
        ];

        /**
         * 验证规则-非必须
         */
        public const array RULES_NOT_MUST = [
                'menuIds' => 'filled|array',
                'menuId' => 'filled|required',
                'pid' => 'filled|integer',
                'name' => 'filled|string|between:1,50',
                'title' => 'filled|string|between:1,50',
                'route' => 'filled|string|between:1,50',
                'path' => 'filled|string|between:1,50',
                'activePath' => 'filled|string|between:1,50',
                'link' => 'filled|string|between:1,250',
                'icon' => 'filled|string|between:1,50',
                'permissionMark' => 'filled|string|between:1,50',
                'queryParams' => 'filled|json|between:1,255',
                'pathParams' => 'filled|json|between:1,255',
                'badgeText' => 'filled|string|between:1,50',
        ];

        /**
         * 验证
         * @param array $data
         * @param array $field
         * @param array $fieldNotMust
         * @throws Exception
         */
        public function validate(array $data, array $field = [], array $fieldNotMust = []): void
        {
                $arrRules = array_merge(
                        array_intersect_key(self::RULES, array_flip($field)),
                        array_intersect_key(self::RULES_NOT_MUST, array_flip($fieldNotMust))
                );
                $validator = $this->validationFactory->make($data, $arrRules, trans('validator'));
                if ($validator->fails()) {
                        $strErrorMessage = $validator->errors()->all()[0];
                        foreach ($field as $v) {
                                $strErrorMessage = str_replace(
                                        str_replace('_', ' ', StrCache::snake($v)),
                                        trans('menu.field.' . $v), $strErrorMessage
                                );
                        }
                        throw new Exception($strErrorMessage);
                }
        }
}